﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using WordBinder.Binder;
using System.Drawing;

namespace WordBinder.UnitTests
{
    [TestClass]
    public class Binder
    {
        [TestMethod]
        public void GetValueTest()
        {
            var firstName = "Test";
            var name = new { First = firstName, Second = "Object" };
            var obj = new
            {
                Name = name,
                Things = new[]
                {
                    new{Name="One", Value = 1},
                    new{Name="Two", Value = 2},
                    new{Name="Three", Value = 3},
                },
                Numbers = new[]
                {
                    new{Name=1, Value = 1},
                    new{Name=2, Value = 2},
                    new{Name=3, Value = 3},
                }
            };

            {
                var result = obj.Query("Name.First");
                Assert.AreEqual(1, result.Count());
                Assert.AreEqual(firstName, result.ElementAt(0));
            }

            {
                var result = obj.Query("Numbers[Name=3].Value");
                Assert.AreEqual(1, result.Count());
                Assert.AreEqual(3, result.ElementAt(0));
            }

            {
                var result = obj.Query("Things[Name=Two].Value");
                Assert.AreEqual(1, result.Count());
                Assert.AreEqual(2, result.ElementAt(0));
            }

            {
                var result = obj.Query("Name[First=" + firstName + "]");
                Assert.AreEqual(1, result.Count());
                Assert.AreEqual(name, result.ElementAt(0));
            }

            {
                var result = obj.Query("Things");
                Assert.AreEqual(3, result.Count());
            }
        }

        [TestMethod]
        public void SelectSingle()
        {
            var data = new
            {
                Root = new
                {
                    Numbers = new[]
                    {
                        new{Name=1, Value = 1},
                        new{Name=2, Value = 2},
                        new{Name=3, Value = 3},
                    },
                    Parent = new { Child = 1 },
                    Strings = new[]
                    {
                        new{Name="One", Value = 1},
                        new{Name="Two", Value = 2},
                        new{Name="Three", Value = 3},
                    }
                }
            };
            { 
            var result = data.SelectSingle("Root.Numbers[Name=1]");
            Assert.AreEqual(result, new { Name = 1, Value = 1 });
            }
            { 
            var result = data.SelectSingle("Root.Numbers[Name=1].Value");
            Assert.AreEqual(result, 1);
            }
            { 
            var result = data.SelectSingle("Root.Strings[Name=One]");
            Assert.AreEqual(result, new { Name = "One", Value = 1 });
            }
            {
            var result = data.SelectSingle("Root.Strings[Name=One].Value");
            Assert.AreEqual(result, 1);
            }
            { 
            var result = data.SelectSingle("Root.Parent.Child");
            Assert.AreEqual(result, 1);
            }
        }

        [TestMethod]
        public void Features()
        {
            var binder = new ReflectBinder();
            var template = Path.Combine(Environment.CurrentDirectory, "TemplateFeatures.docx");

            Image gifImg = Image.FromFile("xml.gif");
            
            var data = new
            {
                @decimal = 10.3,
                replace = 1,
                headers = new
                {
                    first = "Header first page",
                    even = "Header even page",
                    odd = "Header odd page"
                },
                image = gifImg
            };

            var map = new Map
            {
                Header = new ComplexItem
                {
                    //Default
                    //Type = ComplexType.Items,
                    SimpleItems = new List<SimpleItem> 
                    { 
                        new SimpleItem
                        {
                            Key = "{headerfirst}",
                            XPath = "headers.first",
                        },
                        new SimpleItem
                        {
                            Key = "{headereven}",
                            XPath = "headers.even",
                        },
                        new SimpleItem
                        {
                            Key = "{headerodd}",
                            XPath = "headers.odd",
                        },
                    }
                },
                Body = new ComplexItem
                {
                    //Default
                    //Type = ComplexType.Items,
                    SimpleItems = new List<SimpleItem> 
                    {
                        new SimpleItem
                        {
                            Key = "{decimal}",
                            XPath = "decimal",
                            Format = "{0:c}"
                        },
                        new SimpleItem
                        {
                            Key = "{replace}",
                            XPath = "replace",
                            Masks = new List<Mask>
                            {
                                new Mask
                                {
                                    Value = 0,
                                    Replace = "No"
                                },
                                new Mask
                                {
                                    Value = 1,
                                    Replace = "Yes"
                                }
                            }
                        }
                    },
                    ImageItems = new List<ImageItem>
                    {
                        new ImageItem
                        {
                            XPath = "image",
                            Key = "{image}",
                            Type = ImageType.Image
                        }
                    }
                }
            };

            binder.BuildDocument(template, data, map);
        }

        [TestMethod]
        public void RepeatingTable()
        {
            var binder = new ReflectBinder();
            var template = Path.Combine(Environment.CurrentDirectory, "TemplateRepeatingTable.docx");

            var data = new
            {
                Group1 = new[]
                {
                    new {Field1 = "Field1", Field2 = "Field2"},
                    new {Field1 = "Field1", Field2 = "Field2"},
                    new {Field1 = "Field1", Field2 = "Field2"},
                },
            };
            var map = new Map
            {
                Body = new ComplexItem
                {
                    RootNodePath = "Group1",
                    Type = ComplexType.Table,
                    SimpleItems = new List<SimpleItem> 
                    {
                        new SimpleItem { Key = "{Field1}", XPath= "Field1"},
                        new SimpleItem { Key = "{Field2}", XPath= "Field2"}
                    },
                }
            };
            binder.BuildDocument(template, data, map);
        }

        [TestMethod]
        public void RepeatingTypes()
        {
            var binder = new ReflectBinder();
            var template = Path.Combine(Environment.CurrentDirectory, "TemplateRepeatingTypes.docx");

            var data = new
            {
                Group1 = new
                {
                    Field1 = "Field1", 
                    Field2 = "Field2",
                    Group2 = new[]
                    {
                        new {Field1 = "Field1", Field2 = "Field2"},
                        new {Field1 = "Field1", Field2 = "Field2"},
                        new {Field1 = "Field1", Field2 = "Field2"},
                    }
                },
            };
 
            var map = new Map
            {
                Body = new ComplexItem
                {
                    RootNodePath = "Group1",
                    Type = ComplexType.Table,
                    SimpleItems = new List<SimpleItem> 
                    {
                        new SimpleItem { Key = "{Field1}", XPath= "Field1"},
                        new SimpleItem { Key = "{Field2}", XPath= "Field2"}
                    },
                    ComplexItems = new List<ComplexItem> 
                    {
                        new ComplexItem 
                        {
                            Type = ComplexType.Rows,
                            RootNodePath = "Group2",
                            SimpleItems = new List<SimpleItem> 
                            {
                                new SimpleItem { Key = "{Field1}", XPath= "Field1"},
                                new SimpleItem { Key = "{Field2}", XPath= "Field2"}
                            },
                        },
                    }
                }
            };
            binder.BuildDocument(template, data, map);
        }

        [TestMethod]
        public void NestedRepeating()
        {
            var binder = new ReflectBinder();
            var template = Path.Combine(Environment.CurrentDirectory, "TemplateNestedRepeating.docx");

            var data = new data
            {
                Groups = new List<Group>
                {
                    new Group
                    {
                        Field1 = "Parent1",
                        Field2 = "Parent2",
                        Childs = new List<Group>
                        {
                            new Group
                            {
                                Field1 = "Child1",
                                Field2 = "Child2",
                            },
                            new Group
                            {
                                Field1 = "Child3",
                                Field2 = "Child4",
                            },
                        }
                    },
                    new Group
                    {
                        Field1 = "Parent3",
                        Field2 = "Parent4",
                        Childs = new List<Group>
                        {
                            new Group
                            {
                                Field1 = "Child5",
                                Field2 = "Child6",
                            },
                            new Group
                            {
                                Field1 = "Child7",
                                Field2 = "Child8",
                            },
                        }
                    }
                }
            };
 
            var map = new Map
            {
                Body = new ComplexItem
                {
                    RootNodePath = "Groups",
                    Type = ComplexType.Table,
                    SimpleItems = new List<SimpleItem> 
                    {
                        new SimpleItem { Key = "{Field1}", XPath= "Field1"},
                        new SimpleItem { Key = "{Field2}", XPath= "Field2"}
                    },
                    ComplexItems = new List<ComplexItem> 
                    {
                        new ComplexItem 
                        {
                            Type = ComplexType.Table,
                            RootNodePath = "Childs",
                            SimpleItems = new List<SimpleItem> 
                            {
                                new SimpleItem { Key = "{Field1}", XPath= "Field1"},
                                new SimpleItem { Key = "{Field2}", XPath= "Field2"}
                            },
                        },
                    }
                }
            };
            binder.BuildDocument(template, data, map);
        }
    }

    public class data
    {
        public List<Group> Groups {get;set;}
    }

    public class Group
    {
        public string Field1 { get; set; }
        public string Field2 { get; set; }

        public List<Group> Childs { get; set; }
    }
}
